javascript DOM编程小结

本篇文章是对《JavaScript DOM 编程艺术(第二版)》(这本)的笔记式总结。书中涉及的操作 DOM 的方法为常用的核心方法,并不是所有的都介绍了,比较基础简单。作者用一个个生动的例子贯穿了 DOM 的大多数的知识点,还包括浏览器兼容性,网页的可读性,HTML5 以及一些库的简单介绍等。

什么是 DOM

DOM 即 Document Object Model,文档对象模型的缩写,即是一个文档的对象表示形式。DOM 所包含的信息与文档所包含的信息一致,因此可以使用编程语言来操作 DOM 对象,从而达到操作文档的目的。

  • Document

文档,文档是 DOM 的基石,没有文档一切无从谈起。在 web 中文档通常是 (X)HTML。当浏览器加载一个 web 网页时,web 文档就被转化为 DOM 对象。

  • Object

对象,对象是一种自足的数据集合。JavaScript 中对象可以分为三种类型:用户自定义对象,由程序员自行创建;内建对象,内建在 JavaScript 语言中的对象,如,Array;宿主对象,web 中由浏览器提供的对象(node为node环境)。

  • Model

模型,DOM 把一份文档表示为一棵家谱树,使用 parent, child, sibling 等来表示家族成员的关系,这里的树即为模型。

节点类型

元素节点
属性节点
文本节点

节点属性

  • nodeType 属性

每个节点都有 nodeType 属性表示节点的类型
元素节点的 nodeType 属性值为 1
属性节点的 nodeType 属性值为 2
文本节点的 nodeType 属性值为 3

  • nodeValue 属性

节点的值。值得注意的是,要通过 nodeValue 属性获取类似于 \<p> 这种元素节点的文本值,得获取其子节点(文本节点)的 nodeValue 值

  • parentNode 属性

获取一个元素的父节点

  • childNodes 属性

获取一个元素的所有子节点,它是一个包含这个元素的全部子节点的数组。只有元素节点才有子节点

  • nextSibling 属性

获取一个元素的下一个兄弟节点,可能是文本节点

  • firstChild 和 lastChild 属性

node.firstChild 等价于 node.childNodes[0]
node.lastChild 等价于 node.childNodes[node.childNodes.length-1]

  • style 属性

返回一个对象,对象中包含元素的样式。可以使用 element.style.property 来读取/设置样式(property)的值。
当需要引用中间带 “-“ 的 css 属性时,需要用驼峰命名法,如 font-family 就用 fontFamily。
style 属性只能返回内嵌的样式,在 css 文件或者 style 标签中的样式都无法返回。

获取元素节点的主要方式

  • getElementById

document.getElementById(id),通过 id 获取元素节点,返回一个元素节点的 DOM 对象

  • getElementsByTagName

document.getElementsByTagName(tagName),通过标签名获取元素节点,返回一个元素节点 DOM 对象的数组。如果使用 “*” 通配符则返回包含该文档所有节点的数组。

  • getElementsByClassName

document.getElementsByClassName(className),通过类名获取元素节点,返回一个元素节点 DOM 对象的数组。指定多个类名时,只需要使用空格分开即可,并且类名的顺序不重要。

获取和设置元素节点的属性

使用上面介绍的方法获取到元素节点对象后,可以使用以下方式获取/设置元素节点的属性值

  • getAttribute

elementObj.getAttribute(attribute),获取 attribute 属性的属性值

  • setAttribute

elementObj.setAttribute(attribute, value),将 attribute 属性的属性值设置为 value

创建和插入节点

在创建的节点插入文档之前,它还不属于 DOM 节点树的组成部分,此时称为文档碎片。虽然它还不能在浏览器中显示,但是它已经拥有了自己的 DOM 属性。

  • createElement

document.createElement(nodeName),创建一个新的元素节点

  • createTextNode

document.createTextNode(text),创建一个新的文本节点

  • appendChild

parent.appendChild(child),在 parent 元素的末尾插入 child 节点

  • insertBefore

parent.insertBefore(new, target),在 parent 中,将 new 插入在 target 之前,其中 parent 可以通过 target.parentNode 获取

DOM Core 与 HTML-DOM

前面介绍的属性和方法都输入 DOM Core 的组成部分,它们并不专属于 JavaScript,支持 DOM 的任何一种程序设计语言都可以使用它们,同时它们还可以处理任何一种标记语言(如,XML)编写出来的文档。
在使用 JavaScript 和 DOM 为 HTML 编写脚本时,还有许多属性可以选择,如 onclick 属性,可以用于点击事件绑定,这些都输入 HTML-DOM 的组成部分。很多情况下,HTML-DOM 属性和 DOM Core 可以互相替换,如下几个例子:
document.getElementsByTagName(“form”) 等价于 document.forms
还有
element.getAttribute(“src”) 等价于 element.src
以及
element.setAttribute(“href”, value) 等价于 element.href = value 等。
通常,HTML-Core 代码会更短一些,但是,它们只能用来处理 web 文档

传统技术

  • document.write

document.write 方法可以方便快捷的将字符串插入文档中,而且能极好的兼容低版本的浏览器,但是其最大的缺点是违背了“行为与表现分离”的原则,且 MIME 类型为 application/xhtml+xml 与 document.write 不兼容。

  • innerHTML

innerHTML 现在已经包含在 HTML5 的规范中,几乎所有的浏览器都支持。它可以用来读写指定元素里的 HTML 内容,同样 innerHTML 也是 HTML 专属的,不兼容 application/xhtml+xml。

平稳退化与渐进增强

  • 平稳退化

如果在网站的访问者在浏览器端禁用了 JavaScript 的时候,依然可以顺利的浏览网页,这就是”平稳退化”,虽然效果可能有所缺失,但是基本功能能够顺利使用。
一个例子:使用
window.open(url,name,features)
方法在一个新的窗口打开一个连接链接。封装一个方法

1
2
3
function popUp(winURL){
window.open(winURL,"popup","width=320,height=480");
}

在 \<a> 标签中使用该方法,当点击 a 标签时,会在新窗口上打开该链接。

1
2
<a onclick="popUp("http://www.runnerjian.com");
return false;">runnerjian</a>

那么问题是,当浏览器的 JavaScript 被禁用的时候,该功能就是失效了。平稳退化的解决办法是给标签的 href 属性加一个真实的值。

1
2
<a href="http://www.runnerjian.com" onclick="popUp(this.href);
return false;">runnerjian</a>

这样,尽管不是在新的窗口打开该链接,但是打开链接的功能还是可以实现的。
另一个”平稳退化”的理解是,在保证较新版浏览器上良好运行的时候,尽可能保证叫老版本的浏览器依然可以正常浏览网页。

  • 渐进增强

“渐进增强”是”平稳退化”退化的反向,一般先保证最基本的功能可以实现,然后在此基础上,使用一些额外的信息层去包裹原始数据,从而使得网页更加人性化,表现出更好的效果。
通常按照”渐进增强”原则创建出来的网页几乎都符合”平稳退化”原则。

HTML5 以及一些库

书中对这部分没有做详细介绍,所以这里罗列一些相关的关键字。

\<section>, \<article>, \<header>, \<footer>
\<canvas>, \<audio>, \<video>
Geolocation, Storage, Drap-and-Drop, Socket, 多线程等

  • 一些库

jQuery, Prototype, YUI, Dojo Toolkit

  • 选择库的原则

是否具备所需要的所有功能;
功能是否过多,过于庞大,很多不需要的功能;
模块化的吗
支持情况怎么样?社区,维护人员等;
是否有文档;
许可是否合适;

一个好用方法

  • addLoadEvent
1
2
3
4
5
6
7
8
9
10
11
function addLoadEvent(func){
var oldonload = window.onload;
if(typeof window.onload != "function"){
window.onload = func;
}else{
window.onload = function(){
oldonload();
func();
}
}
}

为了给全局添加 onload 回调 func,在文档加载完后可以执行 func,但又不能覆盖之前已经添加的 onload 回调。

Loading comments box needs to over the wall